#include "gp_dp8_ctl.h"
#include "sock_msg_ctl.h"
#include "gp_layout_map.h"
#include "stdio.h"
#include "string.h"
#include "../lua/action_msg.h"
#include "resource_manage.h"
#include <unistd.h>

const float coeffmmToStep_Suck = 503.937;//steps/mm //3200 steps<->6.35mm
const float coeffmmToStep_Z = 335.958;//steps/mm //3200 steps<->9.525mm

const float area_cross = 19.635;// suck pump inner r = 4mm
const float coeffUlToSteps_suck = 25.665;// coeffmmToStep_Suck / area_cross;

const float coeffUlToSteps_Z = 26.7347;// coeffmmToStep_Z / area_cross;

const float coeffmmToStep_dp8_1Z = 629.921;//steps/mm //3200 steps<->5.08mm

//const float coeffUlToStep_dp8_1Z = 629.921;//coeffmmToStep_dp8_1Z/pi/r/r container r=


void dp8ActFunc(void * paramIn,void * actResultOut)
{
    if(!paramIn || !actResultOut)
    {
        return;
    }
    printf("enter in dp8ActFunc\n");
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;
    
    if(pstActMsg->msgHead.actType == ACT_PARRAL_MOVE)
    {
        if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_POS)
        {
            location_layout locLayout;
            location_axis locAxis;
            memcpy(&locLayout,((char*)pstActMsg->paramData) + sizeof(int),sizeof(location_layout));
            printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
            locLayout.location_type,
            locLayout.indexX,
            locLayout.indexY,
            locLayout.column_x,
            locLayout.row_y);
            CGpLayout * pstLayout = CGpLayout::get_instance();
            int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
            if(convertRet)
            {
                printf("convert location failed,errorNum:%d\n",convertRet);
            }
            else 
            {
                printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
                
                actSuccess = dp8XY_move(&locAxis);
            }
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_SINGLE_INIT)
    {
        int component = -1;
        memcpy(&component,(char*)pstActMsg->paramData,sizeof(int));
        printf("dp8ActFunc,single init,componet:%d\n",component);
        actSuccess = dp8_single_init(NULL,component);
    }
    else if(pstActMsg->msgHead.actType == ACT_SINGLE_MOVE)
    {
        if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_STEPS)
        {
            int component = -1;
            int steps = 0;
            char * pData = (char*)pstActMsg->paramData;

            memcpy(&component,pData,sizeof(int));
            pData += sizeof(int);

            memcpy(&steps,pData,sizeof(int));


            printf("dp1ActFunc,single move steps:%d,componet:%d\n",steps,component);
            actSuccess = dp8_single_move_steps(&steps,component);
        }

    }
    else if(pstActMsg->msgHead.actType == ACT_MODULE_INIT)
    {
        printf("dp8ActFunc,module init\n"); 
        actSuccess = dp8_module_init(NULL);       
    }
    else if(ACT_TIP_CTL == pstActMsg->msgHead.actType)
    {
        if(pstActMsg->msgHead.paramType == PARAM_GET_TIP)
        {
            printf("dp8ActFunc,get tip\n"); 
            actSuccess = dp8_gettip(pstActMsg);     
        }
        else if(pstActMsg->msgHead.paramType == PARAM_DROP_TIP)
        {
            printf("dp8ActFunc,drop tip\n"); 
            actSuccess = dp8_droptip(pstActMsg);  
        }
        else
        {
            actSuccess = 0;
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_SUCK_LIQUID)
    {
        printf("dp8ActFunc,suck liquid\n"); 
        actSuccess = dp8_suck(pstActMsg);       
    }
    else if(pstActMsg->msgHead.actType == ACT_SPIT_LIQUID)
    {
        printf("dp8ActFunc,spit liquid\n"); 
        actSuccess = dp8_spit(pstActMsg);
        printf("dp8ActFunc,spit liquid ret:%d\n",actSuccess);        
    }
    else if(ACT_JAW_TRANS == pstActMsg->msgHead.actType)
    {
        printf("dp8ActFunc,trans board\n"); 
        actSuccess = dp8_transBoard(pstActMsg->paramData);       
    }
    else if(ACT_PLUNGER_PUMP == pstActMsg->msgHead.actType)
    {
        //printf("ACT_PLUNGER_PUMP,\n");
        if(PARAM_AXIS_MOVE_POS == pstActMsg->msgHead.paramType)
        {
            int component = 0;
            char * ptrData = (char *)pstActMsg->paramData;

            memcpy(&component,ptrData,sizeof(int));
            ptrData += sizeof(int);

            location_layout locLayout;
            memcpy(&locLayout,ptrData,sizeof(location_layout));

            if(component == MT_PUMP)
            {
                int isSuck = 1;
                int suckvolume = locLayout.column_x;
                if(suckvolume < 0)
                {
                    isSuck = 0;
                    suckvolume = 0 - suckvolume;
                }
                actSuccess = dp8_pump_ctl(isSuck, suckvolume);
            }
        }
    }


    msgAckSock * pstResult = (msgAckSock *)actResultOut;

    if(!actSuccess)
    {
        pstResult->status = 1;
    }
    else
    {
        pstResult->status = 0;
    }

}

void dp8_1ActFunc(void * paramIn,void * actResultOut)
{
    if(!paramIn || !actResultOut)
    {
        return;
    }
    printf("enter in dp8_1ActFunc\n");
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;
    
    if(pstActMsg->msgHead.actType == ACT_PARRAL_MOVE)
    {
        if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_POS)
        {
            location_layout locLayout;
            location_axis locAxis;
            memcpy(&locLayout,((char*)pstActMsg->paramData) + sizeof(int),sizeof(location_layout));
            printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
            locLayout.location_type,
            locLayout.indexX,
            locLayout.indexY,
            locLayout.column_x,
            locLayout.row_y);
            CGpLayout * pstLayout = CGpLayout::get_instance();
            int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
            if(convertRet)
            {
                printf("convert location failed,errorNum:%d\n",convertRet);
            }
            else 
            {
                printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
                
                actSuccess = dp8XY_move(&locAxis);
            }
        }
    }
	else if(ACT_TIP_CTL == pstActMsg->msgHead.actType)
    {
        if(pstActMsg->msgHead.paramType == PARAM_GET_TIP)
        {
            printf("dp8_1ActFunc,get tip\n"); 
            actSuccess = dp8_1gettip(pstActMsg);     
        }
        else if(pstActMsg->msgHead.paramType == PARAM_DROP_TIP)
        {
            printf("dp8_1ActFunc,drop tip\n"); 
            actSuccess = dp8_1droptip(pstActMsg);  
        }
        else
        {
            actSuccess = 0;
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_SUCK_LIQUID)
    {
        printf("dp8_1ActFunc,suck liquid\n");

        suck_param stSuckParam;
        memset(&stSuckParam,0,sizeof(suck_param));
        int convertRet = dp8_1convertSuckParam(pstActMsg->paramData,&stSuckParam);
        if(convertRet == 1)
        {
            actSuccess = dp8_1suck(&stSuckParam);
        }
        else
        {
            actSuccess = 0;
        }


    }
    else if(pstActMsg->msgHead.actType == ACT_SPIT_LIQUID)
    {
        printf("dp8_1ActFunc,spit liquid\n");
		tecan_liquid_param stSpitParam;
        memset(&stSpitParam,0,sizeof(suck_param));
        int convertRet = dp8_1convertSpitParam(pstActMsg,&stSpitParam);

        if(convertRet == 1)
        {
            actSuccess = dp8_1_spit_once(&stSpitParam,1);
        }
        else
        {
            actSuccess = 0;
        }       
    }	
    else if(ACT_SPIT_LIQUID_MULTI == pstActMsg->msgHead.actType)
    {
        tecan_liquid_param stSpitParam;
        memset(&stSpitParam,0,sizeof(suck_param));
        location_layout stLayoutData;
        int convertRet = dp8_1convertSpitParam_multi(pstActMsg,&stSpitParam,&stLayoutData);

        if(convertRet == 1)
        {            
            char * spitHoles = (char *)pstActMsg->paramData;
            spitHoles += sizeof(location_layout);
            spitHoles += 3* sizeof(int);

            int dataLen = pstActMsg->msgHead.paramLen - sizeof(location_layout) - 3* sizeof(int);
            actSuccess = dp8_1_spit_multi(&stSpitParam,&stLayoutData,spitHoles,dataLen);
        }
        else
        {
            actSuccess = 0;
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_SINGLE_INIT)
    {
        int component = -1;
        memcpy(&component,(char*)pstActMsg->paramData,sizeof(int));
        //printf("dp1ActFunc,single init,componet:%d\n",component);
        //actSuccess = dp8_single_init(NULL,component);
        move_param moveParam;

        if(MT_DP8_1_AXIS_Z == component || MT_AXIS_Z == component)
        {

            moveParam.sid = SID_DP8_1_Z;
            moveParam.pos = 0;
            moveParam.speed = 20000;
            moveParam.inc_speed = 60000;
            moveParam.dec_speed = 60000;

            actSuccess = uimInitAct_multi(&moveParam,1,20000);
        }
        else if(MT_PUMP == component)
        {
            moveParam.sid = SID_DP8_1_PUMP;
            moveParam.pos = 0;
            moveParam.speed = 4000;
            moveParam.inc_speed = 8000;
            moveParam.dec_speed = 8000;

            actSuccess = uimInitAct_multi(&moveParam,1,20000);
        }
    }
    else if(pstActMsg->msgHead.actType == ACT_MODULE_INIT)
    {
        printf("dp8_1ActFunc,module init\n"); 
        actSuccess = dp8_module_init(NULL);       
    }
    else if(pstActMsg->msgHead.actType == ACT_SINGLE_MOVE)
    {
        printf("dp8_1ActFunc,single move\n"); 
        //printf("dp1ActFunc,single init,componet:%d\n",component);
        //actSuccess = dp8_single_init(NULL,component);

        if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_STEPS)
        {
            int component = -1;
            int steps = 0;
            char * pData = (char*)pstActMsg->paramData;

            memcpy(&component,pData,sizeof(int));
            pData += sizeof(int);

            memcpy(&steps,pData,sizeof(int));


            if(MT_DP8_1_AXIS_Z == component || MT_AXIS_Z == component)
            {
                move_param moveParam;
                moveParam.sid = SID_DP8_1_Z;
                moveParam.pos = steps;
                moveParam.speed = 20000;
                moveParam.inc_speed = 60000;
                moveParam.dec_speed = 60000;

                actSuccess = uimMoveAct_multi(&moveParam,1,20000);
            }
        }
        else if(pstActMsg->msgHead.paramType == PARAM_AXIS_MOVE_POS)
        {
            
        }
             
    }
    else if(ACT_PLUNGER_PUMP == pstActMsg->msgHead.actType)
    {
        //printf("ACT_PLUNGER_PUMP,\n");
        if(PARAM_AXIS_MOVE_POS == pstActMsg->msgHead.paramType)
        {
            int component = 0;
            char * ptrData = (char *)pstActMsg->paramData;

            memcpy(&component,ptrData,sizeof(int));
            ptrData += sizeof(int);

            location_layout locLayout;
            memcpy(&locLayout,ptrData,sizeof(location_layout));

            if(component == MT_PUMP)
            {
                int isSuck = 1;
                int suckvolume = locLayout.column_x;
                if(suckvolume < 0)
                {
                    isSuck = 0;
                    suckvolume = 0 - suckvolume;
                }
                actSuccess = dp8_1_pump_ctl(isSuck, suckvolume);
            }
        }
    }


	
    msgAckSock * pstResult = (msgAckSock *)actResultOut;

    if(!actSuccess)
    {
        pstResult->status = 1;
    }
    else
    {
        pstResult->status = 0;
    }
}
int dp8XY_move(void * paramIn)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;

    move_param moveParam[3];
    moveParam[0].sid = SID_DP8_Z;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;

	moveParam[1].sid = SID_DP8_1_Z;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;

	moveParam[2].sid = SID_DP8_JAWZ;
    moveParam[2].pos = 0;
    moveParam[2].dec_speed = 80000;
    moveParam[2].inc_speed = 80000;
    moveParam[2].speed = 20000;
    int actSuccess = uimMoveAct_multi(moveParam, 3, 20000);

    if(actSuccess != 1)
    {
        printf("dp8 z and go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }
    
    moveParam[0].sid = SID_DP8_X;
    moveParam[0].pos = pstLocAxis->x;
    moveParam[0].dec_speed = 4000;
    moveParam[0].inc_speed = 4000;
    moveParam[0].speed = 8000;

    moveParam[1].sid = SID_DP8_Y;
    moveParam[1].pos = pstLocAxis->y;
    moveParam[1].dec_speed = 64000;
    moveParam[1].inc_speed = 64000;
    moveParam[1].speed = 16000;

    actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    return actSuccess;
}

int dp8XY_move_withoutZup(void * paramIn)
{
    location_axis * pstLocAxis = (location_axis *)paramIn;
    int actSuccess = 0;
    move_param moveParam[3];
    
    moveParam[0].sid = SID_DP8_X;
    moveParam[0].pos = pstLocAxis->x;
    moveParam[0].dec_speed = 4000;
    moveParam[0].inc_speed = 4000;
    moveParam[0].speed = 8000;

    moveParam[1].sid = SID_DP8_Y;
    moveParam[1].pos = pstLocAxis->y;
    moveParam[1].dec_speed = 64000;
    moveParam[1].inc_speed = 64000;
    moveParam[1].speed = 16000;

    actSuccess = uimMoveAct_multi(moveParam, 2, 20000);

    return actSuccess;
}


int dp8_module_init(void * paramIn)
{
    move_param moveParam[3];
    int actSuccess = 0;
    moveParam[0].sid = SID_DP8_Z;//SID_DP8_Z;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;
    moveParam[1].sid = SID_DP8_JAWZ;//SID_DP8_SUCK
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;

    moveParam[2].sid = SID_DP8_SUCK;
    moveParam[2].pos = 0;
    moveParam[2].dec_speed = 80000;
    moveParam[2].inc_speed = 80000;
    moveParam[2].speed = 20000;
    actSuccess = uimInitAct_multi(moveParam, 3, 20000);

    if(actSuccess != 1)
    {
        printf("dp8 z and dp8 suck,jawz go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }

    moveParam[2].sid = SID_DP8_1_PUMP;//SID_DP8_1_PUMP;// SID_DP8_DROPTIP;SID_DP8_1_PUMP
    moveParam[2].pos = 0;
    moveParam[2].dec_speed = 80000;
    moveParam[2].inc_speed = 80000;
    moveParam[2].speed = 20000;

    moveParam[0].sid = SID_DP8_1_Z;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;

    moveParam[1].sid = SID_DP8_DROPTIP;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;
    actSuccess = uimInitAct_multi(moveParam, 3, 20000);

    if(actSuccess != 1)
    {
        printf("dp8 droptip and dp1z dp1pump go to 0 failed,actRet:%d\n",actSuccess);
        return actSuccess;
    }


    moveParam[0].sid = SID_DP8_X;
    moveParam[0].pos = 0;
    moveParam[0].dec_speed = 80000;
    moveParam[0].inc_speed = 80000;
    moveParam[0].speed = 20000;

    moveParam[1].sid = SID_DP8_Y;
    moveParam[1].pos = 0;
    moveParam[1].dec_speed = 80000;
    moveParam[1].inc_speed = 80000;
    moveParam[1].speed = 20000;

    moveParam[2].sid = SID_DP8_JAW;
    moveParam[2].pos = 0;
    moveParam[2].dec_speed = 8000;
    moveParam[2].inc_speed = 8000;
    moveParam[2].speed = 2000;
    actSuccess = uimInitAct_multi(moveParam, 3, 20000);

    if(actSuccess != 1)
    {
        printf("dp8_module_init, x, y init,actRet:%d\n",actSuccess);
    }
    return actSuccess;
}

int convertToDp8Sid(int componentIn)
{
    int sid = -1;
    switch (componentIn)
    {
        case MT_AXIS_Z:
        {
            sid = SID_DP8_Z;
        }
        break;
        case MT_AXIS_X:
        {
            sid = SID_DP8_X;
        }
        break;
        case MT_AXIS_Y:
        {
            sid = SID_DP8_Y;
        }
        break;
        case MT_PUMP:
        {
            sid = SID_DP8_SUCK;
        }
        break;
        case MT_JAW:
        {
            sid = SID_DP8_JAW;
        }
        break;
        case MT_JAW_Z:
        {
            sid = SID_DP8_JAWZ;
        }
        break;
        case MT_DP8_ABANDONED_HATCH:
        {
            sid = SID_WASTE_DOOR;
        }
        break;
        case MT_QUIT_TIP_Z:
        {
            sid = SID_DP8_DROPTIP;
        }
        break;
        default:
        break;
    }
    return sid; 
}

int dp8_single_init(void * paramIn,int component)
{
    int sid = convertToDp8Sid(component);
    int actSuccess = 0;
    if(sid==-1)
    {
        return actSuccess;
    }

    move_param moveParam;

    moveParam.sid = sid;
    moveParam.pos = 0;


    moveParam.dec_speed = 80000;
    moveParam.inc_speed = 80000;
    moveParam.speed = 20000;

    
    actSuccess = uimInitAct_multi(&moveParam, 1, 20000);

    return actSuccess;
}

int dp8_single_move_steps(void * paramIn,int component)
{
    int sid = convertToDp8Sid(component);
    int actSuccess = 0;
    if(sid==-1)
    {
        return actSuccess;
    }

    move_param moveParam;
    int * pSteps = (int *)paramIn; 
    moveParam.sid = sid;
    moveParam.pos = *pSteps;

    moveParam.dec_speed = 40000;
    moveParam.inc_speed = 40000;
    moveParam.speed = 10000; 

    if(SID_DP8_X == moveParam.sid)
    {
        moveParam.dec_speed = 4000;
        moveParam.inc_speed = 4000;
        moveParam.speed = 8000;         
    }
        
    actSuccess = uimMoveAct_multi(&moveParam, 1, 20000);

    return actSuccess;
}

const suck_ctl dp8SuckCtlParam[VISCOSITY_DUMMY] = 
{
    {
       .air1 = 50,
       .air2 = 5,
       .speedSuck = 100,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 400,//400 ul/s * 4000inc/1000ul
    },
    {
       .air1 = 6,
       .air2 = 6,
       .speedSuck = 90,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 350,
    },
    {
       .air1 = 7,
       .air2 = 7,
       .speedSuck = 80,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 300,
    }
};

void adjustZPos_Dp8(dynamic_z* z_height_posIn)
{
    CResource_Manage  * pstResManage = getResourceManage();
    
    int tipType = TIP_1000UL;
    if(pstResManage)
    {
        tipType = pstResManage->get_curr_tip_type( MODULE_DP8); 
    }

    if(tipType==TIP_200UL)
    {
        z_height_posIn->z_tube_mouth += 12434;
        z_height_posIn->z_max += 12434; 
    }
    else if(tipType==TIP_50UL)
    {
        z_height_posIn->z_tube_mouth += 12434;
        z_height_posIn->z_max += 12434;
    }
}

void adjustZPos_Dp8_en(dynamic_z* z_height_posIn,int tipTypeIn)
{
   
    int tipType = tipTypeIn;


    if(tipType==TIP_200UL)
    {
        z_height_posIn->z_tube_mouth += 12434;
        z_height_posIn->z_max += 12434; 
    }
    else if(tipType==TIP_50UL)
    {
        z_height_posIn->z_tube_mouth += 12434;
        z_height_posIn->z_max += 12434;
    }
}

void adjustZPos_Dp8_1(dynamic_z* z_height_posIn)
{
    CResource_Manage  * pstResManage = getResourceManage();
    
    int tipType = TIP_1000UL;
    if(pstResManage)
    {
        tipType = pstResManage->get_curr_tip_type( MODULE_DP8_1); 
    }

    if(tipType==TIP_200UL)
    {
        z_height_posIn->z_tube_mouth += 24000;
        z_height_posIn->z_max += 24000; 
    }
    else if(tipType==TIP_50UL)
    {
        z_height_posIn->z_tube_mouth += 24000;
        z_height_posIn->z_max += 24000;
    }
}

int dp8_get_container_type(int locTypeIn)
{
    int ret = -1;

    switch(locTypeIn)
    {
       case DP8_PCR_BUFF_TIP:
       {
           ret = CONTAINER_PCR_BOARD;
       }
       break;
       case DP8_REAGENT:
       {
           ret = CONTAINER_PU_REAGENT2;
       }
       break;
       case DP8_DNA_BUFF_TIP:
       {
           ret = CONTAINER_PCR_BOARD;
       }
       break;
       case DP8_TUBE8_SHAKE:
       {
           ret = CONTAINER_8TUBE;
       }
       break;
       case DP8_DNA_BUFF_TIP_1:
       {
           ret = CONTAINER_PCR_BOARD;
       }
       break;

       default:
        break;
    }
    return ret;
}
int dp8_suck(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        actSuccess = dp8XY_move(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_suck, x,y go to target location failed\n");
        return 0;
    }

    int liquidType = VISCOSITY_LOW;
    int suckVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|liquidtype|suckVolume|isforWaste|remainVolume|tiptype
    memcpy(&liquidType,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);
    memcpy(&suckVolume,pstDataBuff,sizeof(int));
    
    pstDataBuff += sizeof(int);
    int isForMulti = 0;
    memcpy(&isForMulti,pstDataBuff,sizeof(int));

    int remainVolume = 0;//-----this should be dynamically calculated.
    pstDataBuff += sizeof(int);
    //printf("remain hex:%02x,%02x,%02x,%02x\n",pstDataBuff[0],pstDataBuff[1],pstDataBuff[2],pstDataBuff[3]);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));
    printf("DP8 suck, liquidType:%d,isForMulti:%d,remain:%d\n",liquidType,isForMulti,remainVolume);
    
    int volumeAir2 = dp8SuckCtlParam[liquidType].air2;
    
    if(isForMulti)
    {
        volumeAir2 = 0;
    }
    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,suckVolume,isForMulti);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }
    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);


    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }
    int tipType = TIP_1000UL;
    pstDataBuff += sizeof(int);
    memcpy(&tipType,pstDataBuff,sizeof(int));

    printf("DP8 suck, tip type:%d\n",tipType);


    adjustZPos_Dp8_en(&z_height_pos,tipType);

    //dynamic_z pump_height_pos;
    //zlocValid = pstLayout->getZloc_withoutConvert(Z_LOC_DP8_SUCK_PUMP,&pump_height_pos);
    
    //z goto tube mouth. pump goto max pos.
    move_param arrMoveParam[2];

    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = z_height_pos.z_tube_mouth;
    arrMoveParam[0].sid = SID_DP8_Z;

    arrMoveParam[1].dec_speed = 80000;
    arrMoveParam[1].inc_speed = 80000;
    arrMoveParam[1].speed = 20000;
    arrMoveParam[1].pos = 0;
    arrMoveParam[1].sid = SID_DP8_SUCK;


    int moveRet = uimMoveAct_multi(arrMoveParam, 2, 50000);

    if(!moveRet)
    {
        printf("DP8 suck, z go to tube mouth failed\n");
        return 0;
    }

    //suck air1 here
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;

    float volumeAri1 = dp8SuckCtlParam[liquidType].air1;
    arrMoveParam[0].pos = volumeAri1*coeffUlToSteps_suck;//mm_to_steps(volumeAri1/area_cross,16,LEAD_SUCK, 1.8);
    arrMoveParam[0].sid = SID_DP8_SUCK;
    arrMoveParam[0].dir = 1;//move toward origin point.

    actSuccess = uimMoveAct_multi_relative(arrMoveParam,1,5000);
    if(!actSuccess)
    {
        printf("DP8 suck, suck air1 failed\n");
        return 0;
    }

    int volumeSpitBack = dp8SuckCtlParam[liquidType].spitQuan; 
    int liquidMore = dp8SuckCtlParam[liquidType].liquidMore;
    if(isForMulti)
    {
       volumeSpitBack = 0; 
       liquidMore = 15;
    }
    int containerType = dp8_get_container_type(locLayout.location_type);

    dp8_suck_param dp8SuckParam = 
    {
        .quantityRemain = remainVolume,//ul used to calculate the previous height
        .quantityToSuck = suckVolume,//ul 
        .speedSuck = dp8SuckCtlParam[liquidType].speedSuck,//ul/s
        .neckHeight = z_height_pos.z_tube_mouth,//the pos of tube mouth
        .bottomType = containerType,//semisphere, cone//
        .posMax = z_height_pos.z_max,//the z max position
        .volumeSuckMore = liquidMore,// suck more ul
        .volumeSpitBack = volumeSpitBack,//spit back ul
    };

    actSuccess = Dp8Suck(&dp8SuckParam);

    if(!actSuccess)
    {
        printf("DP8 suck, suck liquid failed\n");
        return 0;
    }

    if(volumeAir2)
    {

        //suck air2 here.
        memset(arrMoveParam,0,sizeof(move_param)*2);
        arrMoveParam[0].dec_speed = 80000;
        arrMoveParam[0].inc_speed = 80000;
        arrMoveParam[0].speed = 20000;
        //const float area_cross = 50.265482;
        //float volumeAri2 = dp8SuckCtlParam[liquidType].air2;
        arrMoveParam[0].pos = volumeAir2*coeffUlToSteps_suck ;//mm_to_steps(volumeAri2/area_cross,16,LEAD_SUCK, 1.8);
        arrMoveParam[0].sid = SID_DP8_SUCK;
        arrMoveParam[0].dir = 1;//move toward origin point.

        actSuccess = uimMoveAct_multi_relative(arrMoveParam,1,5000);
        if(!actSuccess)
        {
            printf("DP8 suck, suck air2 failed\n");
            return 0;
        }

    }

    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = 0;
    arrMoveParam[0].sid = SID_DP8_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 20000);

    return actSuccess;

}

int dp8_gettip(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        actSuccess = dp8XY_move(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_gettip, x,y go to target location failed\n");
        return 0;
    }
    int tipType = TIP_1000UL;

    memcpy(&tipType,((char*)pstActMsg->paramData)+sizeof(location_layout),sizeof(int));
    //CGpLayout * pstLayout = CGpLayout::get_instance();
    
    if(locLayout.location_type == DP8_TIP48_BUFF || locLayout.location_type == DP8_TIP48_TRANS)
    {
        tipType = TIP_200UL;
    }
    else if(locLayout.location_type == DP8_TIP48_PURIFY_A 
         || locLayout.location_type == DP8_TIP48_PURIFY_B)
    {
         if(locLayout.indexX)
         {
             tipType = TIP_200UL;
         }
         else
         {
             tipType = TIP_1000UL;
         }
         
    }
    else
    {
        tipType = TIP_1000UL;
    }

    // CResource_Manage  * pstResManage = getResourceManage();

    // if(pstResManage)
    // {
    //    pstResManage->set_curr_tip_type( MODULE_DP8,tipType); 
    // }

    dynamic_z zHeightPos;
    int getZRet = pstLayout->getZloc(locLayout.location_type,&zHeightPos);
    if(!getZRet)
    {
        printf("in dp8_gettip,get z pos failed\n");
        return 0;
    }

    move_param arrMoveParam[2];
    //Z go down
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = zHeightPos.z_tube_mouth;
    arrMoveParam[0].sid = SID_DP8_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);
    if(!actSuccess)
    {
        printf("in dp8_gettip,z go down failed\n");
        return 0;
    }
    //z go up
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = 0;
    arrMoveParam[0].sid = SID_DP8_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);

    return actSuccess;
}

int dp8_1gettip(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();

    if(DP8_TIP48_TRANS == locLayout.location_type)
    {
        locLayout.location_type = DP8_TIP48_BUFF;
    }
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);
        
        actSuccess = dp8XY_move(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_gettip, x,y go to target location failed\n");
        return 0;
    }
    int tipType = TIP_1000UL;

    memcpy(&tipType,((char*)pstActMsg->paramData)+sizeof(location_layout),sizeof(int));
    //CGpLayout * pstLayout = CGpLayout::get_instance();

    dynamic_z zHeightPos;
    int getZRet = pstLayout->getZloc(locLayout.location_type,&zHeightPos);
    if(!getZRet)
    {
        printf("in dp8_gettip,get z pos failed\n");
        return 0;
    }

    move_param arrMoveParam[2];
    int deltaSteps = 100;
    int posDp1Gettip = zHeightPos.z_tube_mouth;

    if(posDp1Gettip > deltaSteps)
    {
        posDp1Gettip = posDp1Gettip - deltaSteps;
    }
    printf("dp8_1 gettip,posDp1Gettip:%d\n",posDp1Gettip);
    //Z go down
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = posDp1Gettip;
    arrMoveParam[0].sid = SID_DP8_1_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);
    if(!actSuccess)
    {
        printf("in dp8_gettip,z go down failed\n");
        return 0;
    }
    //z go up
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = 0;
    arrMoveParam[0].sid = SID_DP8_1_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);

    return actSuccess;
}

int dp8_droptip(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();

    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        door_move stDoorMove;
        stDoorMove.result = 0;
        stDoorMove.doorPos = EN_WASTE_DOOR_DROPTIP8;
        pthread_t doorMoveHandle;
        pthread_create(&doorMoveHandle,NULL,thread_open_waste_door,&stDoorMove);
        
        actSuccess = dp8XY_move(&locAxis);

        pthread_join(doorMoveHandle,NULL);

        if(stDoorMove.result != 1)
        {
            printf("in dp8_droptip, door move failed\n");
            return 0; 
        }
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_droptip, x,y go to target location failed\n");
        return 0;
    }
    //CGpLayout * pstLayout = CGpLayout::get_instance();
    
    dynamic_z zHeightPos;
    int getZRet = pstLayout->getZloc_withoutConvert(Z_LOC_DP8_DROP_TIP,&zHeightPos);
    if(!getZRet)
    {
        printf("in dp8_droptip,get z pos failed\n");
        return 0;
    }

    move_param arrMoveParam[3];
    //2, Z go down
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = zHeightPos.z_tube_mouth;
    arrMoveParam[0].sid = SID_DP8_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);
    if(!actSuccess)
    {
        printf("in dp8_droptip,z go down failed\n");
        return 0;
    }

    dynamic_z dropHeightPos;
    getZRet = pstLayout->getZloc_withoutConvert(Z_LOC_DP8_DROP_TIP_DROP,&dropHeightPos);

    //actSuccess = Dp8Droptip(dropHeightPos.z_max,dropHeightPos.z_tube_mouth);
    //3, droptip
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = dropHeightPos.z_tube_mouth;
    arrMoveParam[0].sid = SID_DP8_DROPTIP;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);

    if(actSuccess!=1)
    {
        printf("in dp8_drop, drop tip motor goto %d failed\n",dropHeightPos.z_tube_mouth);
        return 0;
    }
    //4, z go up,droptip go up
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 32000;
    arrMoveParam[0].pos = 2000;
    arrMoveParam[0].sid = SID_DP8_Z;

    arrMoveParam[1].dec_speed = 80000;
    arrMoveParam[1].inc_speed = 80000;
    arrMoveParam[1].speed = 32000;
    arrMoveParam[1].pos = 2000;
    arrMoveParam[1].sid = SID_DP8_DROPTIP;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);
    if(!actSuccess)
    {
        printf("in dp8_droptip,z go up failed\n");
        return 0;
    }

    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 32000;
    arrMoveParam[0].pos = WASTE_DOOR_CLOSE_POS;
    arrMoveParam[0].sid = SID_WASTE_DOOR;

    arrMoveParam[1].dec_speed = 80000;
    arrMoveParam[1].inc_speed = 80000;
    arrMoveParam[1].speed = 32000;
    arrMoveParam[1].pos = 0;
    arrMoveParam[1].sid = SID_DP8_Z;

    arrMoveParam[2].dec_speed = 80000;
    arrMoveParam[2].inc_speed = 80000;
    arrMoveParam[2].speed = 32000;
    arrMoveParam[2].pos = 0;
    arrMoveParam[2].sid = SID_DP8_DROPTIP;

    actSuccess = uimMoveAct_multi(arrMoveParam, 3, 15000);
    if(!actSuccess)
    {
        printf("in dp8_droptip,waste door close failed\n");
        return 0;
    }

    return actSuccess;
}

int dp8_1droptip(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    int deltaX_deviation = 150;

    //int deltaX_8 = 2000;
    //int deltaY_8 = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    if(locLayout.location_type == DP8_DROPTIP)
    {
        locLayout.location_type = DP8_DROPTIP_1;
    }
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        door_move stDoorMove;
        stDoorMove.result = 0;
        stDoorMove.doorPos = EN_WASTE_DOOR_DROPTIP8_1;
        pthread_t doorMoveHandle;
        pthread_create(&doorMoveHandle,NULL,thread_open_waste_door,&stDoorMove);
        locAxis.x = locAxis.x + deltaX_deviation;
        //locAxis.x += deltaX_8;
        //locAxis.y += deltaY_8;
        actSuccess = dp8XY_move(&locAxis);

        pthread_join(doorMoveHandle,NULL);

        if(stDoorMove.result != 1)
        {
            printf("in dp8_droptip, door move failed\n");
            return 0; 
        }
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_droptip, x,y go to target location failed\n");
        return 0;
    }
    //CGpLayout * pstLayout = CGpLayout::get_instance();
    
    int deltaZ_8 = 25000;//detaz comparing to 8tips(47000 <-> 72000)
    int deltaZ_dev = 200;
    dynamic_z zHeightPos;
    int getZRet = pstLayout->getZloc_withoutConvert(Z_LOC_DP8_DROP_TIP_1,&zHeightPos);
    if(!getZRet)
    {
        printf("in dp8_droptip,get z pos failed\n");
        return 0;
    }

    move_param arrMoveParam[2];
    //2, Z go down
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = zHeightPos.z_tube_mouth + deltaZ_dev;
    arrMoveParam[0].sid = SID_DP8_1_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);
    if(!actSuccess)
    {
        printf("in dp8_droptip,z go down failed\n");
        return 0;
    }

    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 8000;
    arrMoveParam[0].inc_speed = 8000;
    arrMoveParam[0].speed = 4000;
    arrMoveParam[0].pos = locAxis.x - deltaX_deviation;
    arrMoveParam[0].sid = SID_DP8_X;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);
    if(!actSuccess)
    {
        printf("in dp8_droptip,x go to target loc failed\n");
        return 0;
    }

    //4, z go up,droptip go up
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 32000;
    arrMoveParam[0].pos = 2000;
    arrMoveParam[0].sid = SID_DP8_1_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 15000);
    if(!actSuccess)
    {
        printf("in dp8_droptip,z go up failed\n");
        return 0;
    }

    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 32000;
    arrMoveParam[0].pos = WASTE_DOOR_CLOSE_POS;
    arrMoveParam[0].sid = SID_WASTE_DOOR;

    arrMoveParam[1].dec_speed = 80000;
    arrMoveParam[1].inc_speed = 80000;
    arrMoveParam[1].speed = 32000;
    arrMoveParam[1].pos = 0;
    arrMoveParam[1].sid = SID_DP8_1_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 2, 15000);
    if(!actSuccess)
    {
        printf("in dp8_droptip,waste door close failed\n");
        return 0;
    }

    return actSuccess;
}

int dp8_spit_waste_liquid(void)
{
    printf("enter in dp8_spit_waste_liquid\n");
    dynamic_z z_height_pos;
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int zlocValid = pstLayout->getZloc_withoutConvert(Z_LOC_DP8_DROP_LIQUID,&z_height_pos);
    int actSuccess = 0;
    move_param arrMoveParam[2];
    //1,Z go to tube mouth
    memset(arrMoveParam,0,sizeof(move_param)*2);

    arrMoveParam[0].sid = SID_DP8_Z;
    arrMoveParam[0].pos = z_height_pos.z_tube_mouth;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].dec_speed = 80000;

    actSuccess = uimMoveAct_multi(arrMoveParam,1,20000);

    if(actSuccess!=1)
    {
        printf("in dp8_spit_waste_liquid, z go down failed\n");
        return actSuccess;
    }

    //2,spit all liquid

    arrMoveParam[0].sid = SID_DP8_SUCK;
    arrMoveParam[0].pos = 0;
    arrMoveParam[0].speed = 10000;
    arrMoveParam[0].inc_speed = 40000;
    arrMoveParam[0].dec_speed = 40000;

    actSuccess = uimMoveAct_multi(arrMoveParam,1,20000);

    if(actSuccess!=1)
    {
        printf("in dp8_spit_waste_liquid, spit all failed\n");
        return actSuccess;    
    }
    //3, z go up and door go zero
    arrMoveParam[0].sid = SID_DP8_Z;
    arrMoveParam[0].pos = 0;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].inc_speed = 40000;
    arrMoveParam[0].dec_speed = 40000;

    arrMoveParam[1].sid = SID_WASTE_DOOR;
    arrMoveParam[1].pos = 0;
    arrMoveParam[1].speed = 20000;
    arrMoveParam[1].inc_speed = 40000;
    arrMoveParam[1].dec_speed = 40000;

    actSuccess = uimMoveAct_multi(arrMoveParam,2,20000);

    if(actSuccess!=1)
    {
        printf("in dp8_spit_waste_liquid, z go up failed\n"); 
        return actSuccess;     
    }

    arrMoveParam[0].sid = SID_WASTE_DOOR;
    arrMoveParam[0].pos = 325000;
    arrMoveParam[0].speed = 40000;
    arrMoveParam[0].inc_speed = 160000;
    arrMoveParam[0].dec_speed = 160000;

    actSuccess = uimMoveAct_multi(arrMoveParam,1,20000);

    if(actSuccess!=1)
    {
        printf("in dp8_spit_waste_liquid, close waste door failed\n");      
    }

    return actSuccess;    
}


int dp8_spit(void * paramIn)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    pthread_t doorMoveHandle;
    door_move stDoorMove;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        if(locLayout.location_type == DP8_WASTE_LIQUID)
        {            
            stDoorMove.result = 0;
            stDoorMove.doorPos = EN_WASTE_DOOR_WASTE_LIQUID;
            
            pthread_create(&doorMoveHandle,NULL,thread_open_waste_door,&stDoorMove);
        }
        actSuccess = dp8XY_move(&locAxis);
        if(locLayout.location_type == DP8_WASTE_LIQUID)
        {
            pthread_join(doorMoveHandle,NULL);
        }
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_spit, x,y go to target location failed\n");
        return 0;
    }

    if(locLayout.location_type == DP8_WASTE_LIQUID)
    {

        printf("door open result:%d\n",stDoorMove.result);
        if(stDoorMove.result!=1)
        {
            printf("in dp8_spit,waste liquid door open failed\n");
            return 0;
        }
        else
        {
            return dp8_spit_waste_liquid();
        }
        
    }

    unsigned char liquidType = VISCOSITY_LOW;
    int spitVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|spitVolume|isformulti|remainVolume
    // memcpy(&liquidType,pstDataBuff,sizeof(int));

    // pstDataBuff += sizeof(int);
    //memcpy(&spitVolume,pstDataBuff,sizeof(int));



    // printf("liquidType:%d,volume:%d\n",liquidType,spitVolume);
    // if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    // {
    //     printf("in dp8_spit, liquidType is %d,change to VISCOSITY_LOW\n");
    //     liquidType = VISCOSITY_LOW;
    // }

    CResource_Manage  * pstResManage = getResourceManage();

    if(pstResManage)
    {
        liquidType = pstResManage->get_curr_liquid_type( DP8_LIQUID_TYPE); 
    }

    int remainVolume = 1000;//-----this should be dynamically calculated.


    // float deltaHeightToAdd = 0;
    // int retHeight = volumeToHeight(spitVolume, TUBE_BOTTOM_SEMISPHERE, &deltaHeightToAdd);

    // if(retHeight)
    // {
    //     printf("delta height is not valid\n");
    //     return 0;
    // }
    //pstDataBuff += sizeof(int);
    memcpy(&spitVolume,pstDataBuff,sizeof(int));

    int isForWaste = 0;
    pstDataBuff += sizeof(int);
    memcpy(&isForWaste,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));

    float heightAfterSpit = 0;

    int containerType = CONTAINER_8TUBE;

    if(locLayout.location_type == DP8_TUBE8_SHAKE)
    {
        containerType = CONTAINER_8TUBE;
    }
    else if(locLayout.location_type == DP8_DNA_BUFF_TIP
        || locLayout.location_type == DP8_PCR_BUFF_TIP)
    {
        containerType = CONTAINER_PCR_BOARD;
    }

    int retHeight = volumeToHeight_en(remainVolume + spitVolume, containerType, &heightAfterSpit);
    if(retHeight)
    {
        printf("remain height is not valid\n");
        return 0;
    }

    //float z_steps_per_mm = 335.958; //

    int deltaSteps = (int)(coeffmmToStep_Z*heightAfterSpit);

    //get z max and tube mouth
    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    if(!zlocValid||((z_height_pos.z_max - z_height_pos.z_tube_mouth)<=0))
    {
        printf("z location is not valid\n");
        return 0;
    }

    if(deltaSteps > (z_height_pos.z_max - z_height_pos.z_tube_mouth))
    {
        printf("delta z is not valid\n");
        return 0;
    }

    int tipType = TIP_1000UL;
    pstDataBuff += sizeof(int);
    memcpy(&tipType,pstDataBuff,sizeof(int));

    adjustZPos_Dp8_en(&z_height_pos,tipType);

    printf("spit z_max:%d,z tube mouth:%d\n",z_height_pos.z_max,z_height_pos.z_tube_mouth);

    move_param arrMoveParam[2];
    //1,Z go to tube mouth
    memset(arrMoveParam,0,sizeof(move_param)*2);

    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;

    arrMoveParam[0].speed = 20000;//mm_to_steps(400 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].pos = z_height_pos.z_tube_mouth;
    arrMoveParam[0].sid = SID_DP8_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 8000);

    if(actSuccess!=1)
    {
        printf("dp8_spit,Z goto tube mouth failed\n");
        return 0;
    } 

    //2,spit out the air2
    memset(arrMoveParam,0,sizeof(move_param)*2);

    int delta_steps_suck = dp8SuckCtlParam[liquidType].air2*coeffUlToSteps_suck;// mm_to_steps(dp8SuckCtlParam[liquidType].air2 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;

    arrMoveParam[0].speed = 400 * coeffUlToSteps_suck;//mm_to_steps(400 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].pos = delta_steps_suck;
    arrMoveParam[0].sid = SID_DP8_SUCK;
    arrMoveParam[0].dir = 0;//suck pump move away origin

    actSuccess = uimMoveAct_multi_relative(arrMoveParam, 1, 10000);

    if(actSuccess!=1)
    {
        printf("dp8_spit,spit out air2 failed\n");
        return 0;
    }

        //3, z go to liquid face that after spit

        printf("height after spit:%f,deltaSteps:%d,pos after spit:%d\n",
        heightAfterSpit,deltaSteps,z_height_pos.z_max - deltaSteps);
    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;

    arrMoveParam[0].speed = 20000;//mm_to_steps(400 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].pos = z_height_pos.z_max - deltaSteps;
    arrMoveParam[0].sid = SID_DP8_Z;
    arrMoveParam[0].dir = 1;//

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 10000);
    if(actSuccess!=1)
    {
        printf("dp8_spit,z go to liquid face failed\n");
        return 0;
    } 

    //4,spit liquid here
    memset(arrMoveParam,0,sizeof(move_param)*2);
    
    delta_steps_suck = spitVolume*coeffUlToSteps_suck;// mm_to_steps(dp8SuckCtlParam[liquidType].air2 / area_cross, 16,LEAD_SUCK, 1.8);
    printf("spitVolume:%d,delta_steps_suck:%d\n",spitVolume,delta_steps_suck);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;

    arrMoveParam[0].speed = 400 * coeffUlToSteps_suck;//mm_to_steps(400 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].pos = delta_steps_suck;
    arrMoveParam[0].sid = SID_DP8_SUCK;
    arrMoveParam[0].dir = 0;//suck pump move away origin

    actSuccess = uimMoveAct_multi_relative(arrMoveParam, 1, 10000);
    if(actSuccess!=1)
    {
        printf("dp8_spit,spit liquid failed\n");
        return 0;
    }
    //5,delay after spitting
    usleep(300000);
    //6, z go back to tube mouth
    memset(arrMoveParam,0,sizeof(move_param)*2);

    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;

    arrMoveParam[0].speed = 20000;//mm_to_steps(400 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].pos = z_height_pos.z_tube_mouth;
    arrMoveParam[0].sid = SID_DP8_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 8000);

    if(actSuccess!=1)
    {
        printf("dp8_spit,Z go back to tube mouth failed\n");
        return 0;
    }

    //7, suck back air2 
    int volumeSuckBack = 5;
    int speedSuckBack = 50;
    memset(arrMoveParam,0,sizeof(move_param)*2);

    delta_steps_suck = volumeSuckBack*coeffUlToSteps_suck;// mm_to_steps(dp8SuckCtlParam[liquidType].air2 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;

    arrMoveParam[0].speed = speedSuckBack * coeffUlToSteps_suck;//mm_to_steps(400 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].pos = delta_steps_suck;
    arrMoveParam[0].sid = SID_DP8_SUCK;
    arrMoveParam[0].dir = 1;//suck pump move away origin

    actSuccess = uimMoveAct_multi_relative(arrMoveParam, 1, 10000);
    if(actSuccess!=1)
    {
        printf("dp8_spit,spit liquid failed\n");
        return 0;
    }
    //8, z go back to zero
    memset(arrMoveParam,0,sizeof(move_param)*2);

    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;

    arrMoveParam[0].speed = 20000;//mm_to_steps(400 / area_cross, 16,LEAD_SUCK, 1.8);
    arrMoveParam[0].pos = 0;
    arrMoveParam[0].sid = SID_DP8_Z;

    actSuccess = uimMoveAct_multi(arrMoveParam, 1, 8000);

    if(actSuccess!=1)
    {
        printf("dp8_spit,Z go back to tube mouth failed\n");
        return 0;
    }

    return actSuccess;
}


int Dp8Suck(const void * paramIn)
{
    dp8_suck_param * pstSuckParam = (dp8_suck_param *)paramIn;

    if(pstSuckParam->quantityRemain < pstSuckParam->quantityToSuck)
    {
        printf("the liquid is not enough,remain:%d,suck:%d",pstSuckParam->quantityRemain,pstSuckParam->quantityToSuck);
        return 0;
    }

    //1,calc the height according to the remain liquid
    float liquid_height = 0;
    int convertRet = 0;
    convertRet = volumeToHeight_en(pstSuckParam->quantityRemain,pstSuckParam->bottomType,&liquid_height); 

    if(convertRet)
    {
        printf("the remain volume is not valid\n");
        return 0;
    }
    

    float post_height = 0;
    int volumePost = pstSuckParam->quantityRemain - pstSuckParam->quantityToSuck - pstSuckParam->volumeSuckMore;
    if(volumePost<0)
    {
        volumePost = 0;
    }
    convertRet = volumeToHeight_en(volumePost,pstSuckParam->bottomType,&post_height);
    
    if(convertRet)
    {
        printf("the post height is not valid\n");
        return 0;
    }

    
    float delta_height = liquid_height -  post_height;

    int delta_steps_z = 0;//mm_to_steps(delta_height,16,LEAD_Z,1.8);

    if(delta_height < 0.000001)
    {
        printf("delta height is not valid,%f\n",delta_height);

        printf("liquid_height:%f,liquid_height:%f\n",liquid_height,post_height);

        printf("volumeRemain:%d,volumeSuck:%d,volumeMore:%d\n",
        pstSuckParam->quantityRemain,
        pstSuckParam->quantityToSuck,
        pstSuckParam->volumeSuckMore);
        delta_steps_z = 0;
        //return 0;
    }
    else
    {
        delta_steps_z = delta_height* coeffmmToStep_Z;
    }
    
    int delta_steps_suck = (pstSuckParam->quantityToSuck + pstSuckParam->volumeSuckMore)*coeffUlToSteps_suck ;//mm_to_steps(delta_height,16,LEAD_SUCK,1.8);


    //const float MAX_SUCK_DISTANCE = 38000;

    //0.1 the following action should be done after air1 has suck in.

    //1 z go to liquid height, suck pump go to max distance

    int pos_z_liquid = pstSuckParam->posMax - liquid_height*coeffmmToStep_Z;//mm_to_steps(liquid_height,16,LEAD_Z,1.8);
    printf("Dp8Suck, z_max:%d,liquid_height:%f,pos_z_liquid:%d\n",
    pstSuckParam->posMax,liquid_height,pos_z_liquid);
    //
    move_param arrMoveParam[2];

    memset(arrMoveParam,0,sizeof(move_param)*2);
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 20000;
    arrMoveParam[0].pos = pos_z_liquid;
    arrMoveParam[0].sid = SID_DP8_Z;

    // arrMoveParam[1].dec_speed = 80000;
    // arrMoveParam[1].inc_speed = 80000;
    // arrMoveParam[1].speed = 20000;
    // arrMoveParam[1].pos = MAX_SUCK_DISTANCE;
    // arrMoveParam[1].sid = SID_DP8_SUCK;


    int moveRet = uimMoveAct_multi(arrMoveParam, 1, 12000);

    if(!moveRet)
    {
        printf("DP8 suck, z go to liquid face failed\n");
    }


    //2, suck liquid and the z go down at the same time
    memset(arrMoveParam,0,sizeof(move_param)*2);

    int moveNum = 2;
    if(delta_steps_z == 0)
    {
       moveNum = 1;
    }

    int timeSuck_ms = pstSuckParam->quantityToSuck * 1000 /pstSuckParam->speedSuck;

    timeSuck_ms += 500;
    int timeSuck = timeSuck_ms/1000;
    //const float area_cross = 50.265482;
    arrMoveParam[1].speed = delta_steps_z / timeSuck ;///pstSuckParam->speedSuck*coeffUlToSteps_Z;//mm_to_steps(pstSuckParam->speedSuck / area_cross, 16,LEAD_Z, 1.8); 
    arrMoveParam[1].dec_speed = arrMoveParam[1].speed * 4;
    arrMoveParam[1].inc_speed = arrMoveParam[1].speed * 4;    
    arrMoveParam[1].pos = delta_steps_z;
    arrMoveParam[1].sid = SID_DP8_Z;
    arrMoveParam[1].dir = 1;//dp8 z move away origin

    arrMoveParam[0].speed = pstSuckParam->speedSuck*coeffUlToSteps_suck;
    arrMoveParam[0].dec_speed = arrMoveParam[0].speed * 4;
    arrMoveParam[0].inc_speed = arrMoveParam[0].speed * 4;
    //arrMoveParam[0].speed = pstSuckParam->speedSuck*coeffUlToSteps_suck;//mm_to_steps(pstSuckParam->speedSuck / area_cross, 16,LEAD_SUCK, 1.8);;
    arrMoveParam[0].pos = delta_steps_suck;
    arrMoveParam[0].sid = SID_DP8_SUCK;
    arrMoveParam[0].dir = 1;//suck pump move to origin

    moveRet = uimMoveAct_multi_relative(arrMoveParam, moveNum, 80000);
    //wait after suck,
    usleep(1000000);
    //2.1 spit back here.   

    //delta_height = pstSuckParam->volumeSpitBack;
    if(pstSuckParam->volumeSpitBack)
    {
        memset(arrMoveParam,0,sizeof(move_param)*2);
        delta_steps_suck = pstSuckParam->volumeSpitBack*coeffUlToSteps_suck; //mm_to_steps(pstSuckParam->volumeSpitBack / area_cross, 16,LEAD_SUCK, 1.8);
        arrMoveParam[0].dec_speed = 80000;
        arrMoveParam[0].inc_speed = 80000;
        arrMoveParam[0].speed = pstSuckParam->speedSuck*coeffUlToSteps_suck;//mm_to_steps(pstSuckParam->speedSuck / area_cross, 16,LEAD_SUCK, 1.8);
        arrMoveParam[0].pos = delta_steps_suck;
        arrMoveParam[0].sid = SID_DP8_SUCK;
        arrMoveParam[0].dir = 0;//suck pump move toward origin

        moveRet = uimMoveAct_multi_relative(arrMoveParam, 1, 8000);
    }

    
    usleep(500000);
    
    //3, z move back up to tube neck

    memset(arrMoveParam,0,sizeof(move_param));
    arrMoveParam[0].dec_speed = 80000;
    arrMoveParam[0].inc_speed = 80000;
    arrMoveParam[0].speed = 40000; 
    arrMoveParam[0].pos = pstSuckParam->neckHeight;
    arrMoveParam[0].sid = SID_DP8_Z;
    
    moveRet = uimMoveAct_multi(arrMoveParam, 1, 50000);
    return moveRet;

    //suck air2 after this action.
    
}


int dp8_transBoard(void * paramIn)
{
    char * pData = (char *)paramIn;

    int actSuccess = 0;

    location_layout locLayoutSrc;
    memcpy(&locLayoutSrc,pData,sizeof(location_layout));

    pData += sizeof(location_layout);
    location_layout locLayoutDst;
    memcpy(&locLayoutDst,pData,sizeof(location_layout));

    CGpLayout * pstLayout = CGpLayout::get_instance();

    location_axis locAxis;
    int posJawOpen = DP8_JAW_OPEN_POS;
    int posJawClose = DP8_JAW_CLOSE_POS;
    int filmId = 0;

    int convertRet = 0;
    int getzRet = 0;

    dynamic_z zloc;

    move_param moveParamArr[2];
    memset(moveParamArr,0,sizeof(move_param)*2);
    
    //1, x,y goto src location
    if(locLayoutSrc.location_type == DP8_PCR_BUFF_TIP)
    {
        locLayoutSrc.location_type = DP8_PCR_BUFF_JAW;
    }

    if(locLayoutSrc.location_type == DP8_FILM_SRC)
    {
        posJawOpen = DP8_JAW_OPEN_POS_FILM;
        posJawClose = DP8_JAW_CLOSE_POS_FILM;
        filmId = locLayoutSrc.indexX;
        locLayoutSrc.indexX = 0;
    }

    if(locLayoutSrc.location_type != 0xffff)
    {
        convertRet = pstLayout->convertToAxisLoc(&locLayoutSrc,&locAxis);

        if(convertRet)
        {
            printf("dp8_transBoard, convert src location failed,errorNum:%d\n",convertRet);
            printf("loctype:%d,exX:%d,exY:%d,columnX:%d,rowY:%d\n",
            locLayoutSrc.location_type,
            locLayoutSrc.indexX,
            locLayoutSrc.indexY,
            locLayoutSrc.column_x,
            locLayoutSrc.row_y);
            actSuccess = 0;
        }
        else 
        {
            printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

            actSuccess = dp8XY_move(&locAxis);
        }

        if(actSuccess != 1)
        {
            printf("dp8_transBoard, x y go to src loc failed\n");
            return 0;
        }
        //2, jaw open

        moveParamArr[0].pos = posJawOpen;
        moveParamArr[0].dec_speed = 8000;
        moveParamArr[0].inc_speed = 8000;
        moveParamArr[0].speed = 4000;

        moveParamArr[0].sid = SID_DP8_JAW;

        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


        if(actSuccess != 1)
        {
            printf("dp8_transBoard, jaw open failed,actRet:%d\n",actSuccess);
            return 0;
        }
        //3, z go down src location 
        
        getzRet = pstLayout->getZloc(locLayoutSrc.location_type, &zloc);
        if(!getzRet)
        {
            printf("dp8_transBoard, get src z failed\n");
            return 0;        
        }
        int srcZPos = zloc.z_tube_mouth;

        if(locLayoutSrc.location_type == DP8_FILM_SRC)
        {
            srcZPos += DELTA_FILM_BOARD_Z*filmId;
        }

        moveParamArr[0].pos = srcZPos;
        moveParamArr[0].dec_speed = 120000;
        moveParamArr[0].inc_speed = 120000;
        moveParamArr[0].speed = 32000;

        moveParamArr[0].sid = SID_DP8_JAWZ;
        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


        if(actSuccess != 1)
        {
            printf("dp8_transBoard, z go down to src failed\n");
            return 0;
        }

        //4, jaw close
        moveParamArr[0].pos = posJawClose;
        moveParamArr[0].dec_speed = 8000;
        moveParamArr[0].inc_speed = 8000;
        moveParamArr[0].speed = 4000;

        moveParamArr[0].sid = SID_DP8_JAW;

        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);

        if(actSuccess != 1)
        {
            printf("dp8_transBoard, jaw close src failed\n");
            return 0;
        }
        //4.2 jaw z go up
        moveParamArr[0].pos = 0;
        moveParamArr[0].dec_speed = 8000;
        moveParamArr[0].inc_speed = 8000;
        moveParamArr[0].speed = 4000;

        moveParamArr[0].sid = SID_DP8_JAWZ;

        actSuccess = uimMoveAct_multi(moveParamArr,1,20000);

        if(actSuccess != 1)
        {
            printf("dp8_transBoard, jawz go up src failed\n");
            return 0;
        }

    }

    if(locLayoutDst.location_type == 0xffff)
    {
        return actSuccess;
    }

    //5, x,y goto dst pos
    if(locLayoutDst.location_type == DP8_PCR_BUFF_TIP)
    {
        locLayoutDst.location_type = DP8_PCR_BUFF_JAW;
    }

    convertRet = pstLayout->convertToAxisLoc(&locLayoutDst,&locAxis);

    if(convertRet)
    {
        printf("dp8_transBoard, convert dst location failed,errorNum:%d\n",convertRet);
        actSuccess = 0;
    }
    else 
    {
        //DELTA_FILM_BOARD_X
        if(locLayoutSrc.location_type == DP8_FILM_SRC)
        {
            locAxis.x += DELTA_FILM_BOARD_X;
        }
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        actSuccess = dp8XY_move(&locAxis);
    }
    if(actSuccess != 1)
    {
        printf("dp8_transBoard, x,y go to dst failed\n");
        return 0;
    }
    //6, z go down
    getzRet = pstLayout->getZloc(locLayoutDst.location_type, &zloc);
    if(!getzRet)
    {
        printf("dp8_transBoard, get dst z failed\n");
        return 0;        
    }

    int zlocDst = zloc.z_tube_mouth;

    if(locLayoutSrc.location_type == DP8_FILM_SRC)
    {
        zlocDst += DELTA_SEAL_Z_FILM; 
    }

    moveParamArr[0].pos = zloc.z_tube_mouth;
    moveParamArr[0].dec_speed = 120000;
    moveParamArr[0].inc_speed = 120000;
    moveParamArr[0].speed = 32000;

    moveParamArr[0].sid = SID_DP8_JAWZ;
    actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


    if(actSuccess != 1)
    {
        printf("dp8_transBoard, z go down to dst failed\n");
        return 0;
    }

    //7, jaw  open.
    moveParamArr[0].pos = posJawOpen;
    moveParamArr[0].dec_speed = 8000;
    moveParamArr[0].inc_speed = 8000;
    moveParamArr[0].speed = 4000;

    moveParamArr[0].sid = SID_DP8_JAW;

    actSuccess = uimMoveAct_multi(moveParamArr,1,20000);

    if(actSuccess != 1)
    {
        printf("dp8_transBoard, jaw open dst failed\n");
        return 0;
    }

    //8, z go up.
    moveParamArr[0].pos = 0;
    moveParamArr[0].dec_speed = 120000;
    moveParamArr[0].inc_speed = 120000;
    moveParamArr[0].speed = 32000;

    moveParamArr[0].sid = SID_DP8_JAWZ;
    actSuccess = uimMoveAct_multi(moveParamArr,1,20000);


    if(actSuccess != 1)
    {
        printf("dp8_transBoard, z go up failed\n");
        return 0;
    }

    return actSuccess;
}
const suck_ctl dp8_1SuckCtlParam[VISCOSITY_DUMMY] = 
{
    {
       .air1 = 10,
       .air2 = 5,
       .speedSuck = 100,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 400,//400 ul/s
    },
    {
       .air1 = 6,
       .air2 = 6,
       .speedSuck = 90,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 350,
    },
    {
       .air1 = 7,
       .air2 = 7,
       .speedSuck = 80,
       .liquidMore = 5,
       .spitQuan = 4,
       .spitSpeed = 300,
    }
};

int dp8_1convertSuckParam(void * paramIn, void * paramOut)
{
    char * pstDataBuff = (char *)paramIn;
    int actSuccess = 0;

        //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,pstDataBuff,sizeof(location_layout));
    printf("in dp8_1convertSuckParam, location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);

    CGpLayout * pstLayout = CGpLayout::get_instance();
    if(locLayout.location_type == DP8_DNA_BUFF_TIP)
    {
       locLayout.location_type =  DP8_DNA_BUFF_TIP_1;
    }
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("dp8_1convertSuckParam, convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        actSuccess = dp8XY_move(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_1convertSuckParam, x,y go to target location failed\n");
        return 0;
    }
    int liquidType = VISCOSITY_LOW;
    int suckVolume = 0;
    pstDataBuff += sizeof(location_layout);
    //|xylayout|liquidtype|suckVolume|isformulti|remainVolume
    memcpy(&liquidType,pstDataBuff,sizeof(int));
    
    //store the liquid type
    CResource_Manage  * pstResManage = getResourceManage();



    pstDataBuff += sizeof(int);
    memcpy(&suckVolume,pstDataBuff,sizeof(int));
    
    pstDataBuff += sizeof(int);
    int isForMulti = 0;
    memcpy(&isForMulti,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);

    int remainVolume = 0;
    memcpy(&remainVolume,pstDataBuff,sizeof(int));

    int volumeAir2 = dp8_1SuckCtlParam[liquidType].air2;

    if(isForMulti)
    {
        volumeAir2 = 0;
    }
    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,suckVolume,isForMulti);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }
    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    
    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }   
    

    printf("z tube mouth:%d,z max:%d\n",z_height_pos.z_tube_mouth,z_height_pos.z_max);
    
    //adjustZPos_Dp8_1(&z_height_pos);

    int posPre = z_height_pos.z_tube_mouth;

    suck_param * pstSuckParam = (suck_param *)paramOut;
    
    float liquid_height = 0;
    convertRet = volumeToHeight_en(remainVolume,CONTAINER_PCR_BOARD,&liquid_height); 

    int deltaHeightSteps = liquid_height*coeffmmToStep_dp8_1Z;
    printf("remainVolume:%d,liquid height:%f,delta steps:%d\n",remainVolume,liquid_height,deltaHeightSteps);
    int liquidFaceSteps = z_height_pos.z_max - deltaHeightSteps;

    if(liquidFaceSteps<z_height_pos.z_tube_mouth || liquidFaceSteps > z_height_pos.z_max)
    {
        printf("dp8_1convertSuckParam, liquid face height is invalid,liquidFaceSteps:%d,mouth:%d,z_max:%d\n",
        liquidFaceSteps,z_height_pos.z_tube_mouth,z_height_pos.z_max);
        return 0;
    }

    suck_param tempSuckParam = {
        .posPre = posPre, // this should be change according to the ----
        .speedPre = 20000, // the speed go to previous position
        .air1Quan = dp8_1SuckCtlParam[liquidType].air1, // the air quantity before suck liquid
        .speedDetect = 210,//20mm/s / 0.009525 = 209.973// the speed of detecting liquid face
        .threshold = 9, // the threshold of detecting
        .stepBelow = 10,// the step continue to go after detecting success
        .speedSuck = dp8_1SuckCtlParam[liquidType].speedSuck,// the suck speed
        .quantity = suckVolume, // the suck quantity
        .more = dp8_1SuckCtlParam[liquidType].liquidMore, // the reduntant quantity
        .posMax = z_height_pos.z_max, //the max pos to go if no liquid ----this should be changed.
        .posPost = liquidFaceSteps, // this is calculated through the remain liquid volume.
        .speedPost = 210, // the speed to go to posPost,---equals to speedDetect
        .air2Quan = volumeAir2, // the air quantity after suck liquid    
        .spitQuan = dp8_1SuckCtlParam[liquidType].spitQuan, // spit back quantity
        .speedSuckAir1 = 50,//ul/s
        .delayAfterSuck = 1000, //ms
        .delayAfterSpit = 500, //ms
        .speedSuckAir2 = 50,//ul/s
        .spitSpeed = dp8_1SuckCtlParam[liquidType].spitSpeed,//inc/s
    };

    memcpy(pstSuckParam,&tempSuckParam,sizeof(suck_param));
    return 1;
}

int dp8_1suck(void * paramIn)
{
    suck_param * pstSuckParam = (suck_param *)paramIn;

    int actSuccess = 0;
    int sidx = SID_DP8_X;
    int sidy = SID_DP8_Y;
    int sidz = SID_DP8_1_Z;
    int sidPump = SID_DP8_1_PUMP;

    int z_tube_mouth = 0;
    float coeffUlToSteps_pump = 320;//32000steps<-->100ul for pump

    //1, dp8_1 go down to tube mouth    
    move_param stDp8Move[2];
    stDp8Move[0].sid = sidz;
    stDp8Move[0].pos = pstSuckParam->posPre; //dj go down to tube mouth
    stDp8Move[0].dec_speed = 80000;
    stDp8Move[0].inc_speed = 80000;
    stDp8Move[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDp8Move,1,20000);
    if(actSuccess!=1)
    {
        printf("in dp8_1_suck, z go to pre pos failed\n");
        return 0;
    }
    
    //2,suck air 1
    stDp8Move[0].sid = sidPump;
    stDp8Move[0].pos = pstSuckParam->air1Quan * coeffUlToSteps_pump; //dj go down to tube mouth
    stDp8Move[0].speed = pstSuckParam->speedSuckAir1 * coeffUlToSteps_pump;
    stDp8Move[0].dec_speed = stDp8Move[0].speed * 4;
    stDp8Move[0].inc_speed = stDp8Move[0].speed * 4;
    stDp8Move[0].dir = 1; //move away origin point
      
    actSuccess = uimMoveAct_multi_relative(stDp8Move,1,20000);
    if(actSuccess!=1)
    {
        printf("in dp8_1_suck, suck air1 failed\n");
        return 0;
    }

    //3, z go  down to suck pos    
    stDp8Move[0].sid = sidz;
    //this is the variable calculated through the remain liquid
    stDp8Move[0].pos = pstSuckParam->posPost; 
    stDp8Move[0].dec_speed = 80000;
    stDp8Move[0].inc_speed = 80000;
    stDp8Move[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDp8Move,1,20000);
    if(actSuccess!=1)
    {
        printf("in dp8_1_suck, z go to liquid face failed\n");
        return 0;
    }

    printf("in dp8_1_suck, z go to liquid face:%d ok\n",pstSuckParam->posPost);

    //4, suck and z go down at the same time
    float deltaHeight = 0;
    volumeToHeight(pstSuckParam->quantity,TUBE_BOTTOM_CONE,&deltaHeight);
    
    float speedDp8_1_z = 0;
    volumeToHeight(pstSuckParam->speedSuck,TUBE_BOTTOM_CONE,&speedDp8_1_z);
    stDp8Move[0].sid = sidz;    //
    stDp8Move[0].pos = (int)(coeffmmToStep_dp8_1Z * deltaHeight + 0.5);
    stDp8Move[0].speed = (int)(coeffmmToStep_dp8_1Z * speedDp8_1_z);
    stDp8Move[0].dec_speed = stDp8Move[0].speed * 4;
    stDp8Move[0].inc_speed = stDp8Move[0].speed * 4;
    stDp8Move[0].dir = 1; //go away origin

    stDp8Move[1].sid = sidPump;    //
    stDp8Move[1].pos = coeffUlToSteps_pump * (pstSuckParam->quantity + pstSuckParam->more);
    stDp8Move[1].speed = pstSuckParam->speedSuck * coeffUlToSteps_pump;
    stDp8Move[1].dec_speed = stDp8Move[1].speed * 4;
    stDp8Move[1].inc_speed = stDp8Move[1].speed * 4;
    stDp8Move[1].dir = 1; //go away origin

    actSuccess = uimMoveAct_multi_relative(stDp8Move,2,20000);
    if(actSuccess!=1)
    {
        printf("in dp8_1_suck, suck liquid failed\n");
        return 0;
    }

    if(pstSuckParam->delayAfterSuck > 0)
    {
        usleep(1000*pstSuckParam->delayAfterSuck);
    }

	
	if(pstSuckParam->spitQuan > 0.0001)
	{
	    //5, spit out back    
	    stDp8Move[0].sid = sidPump;
	    stDp8Move[0].pos = pstSuckParam->spitQuan * coeffUlToSteps_pump; //dj go down to tube mouth
	    stDp8Move[0].speed = pstSuckParam->spitSpeed * coeffUlToSteps_pump;
	    stDp8Move[0].dec_speed = stDp8Move[0].speed * 4;
	    stDp8Move[0].inc_speed = stDp8Move[0].speed * 4;
	    stDp8Move[0].dir = 0; //move toward origin point      
	    actSuccess = uimMoveAct_multi_relative(stDp8Move,1,20000);

	    if(actSuccess!=1)
	    {
	        printf("in dp8_1_suck, spit back failed\n");
	        return 0;
	    }
	
	}
    
    if(pstSuckParam->delayAfterSpit > 0)
    {
        usleep(1000*pstSuckParam->delayAfterSpit);
    }
    //6, z go up to pre pos
    stDp8Move[0].sid = sidz;
    stDp8Move[0].pos = pstSuckParam->posPre; //dj go down to tube mouth
    stDp8Move[0].dec_speed = 80000;
    stDp8Move[0].inc_speed = 80000;
    stDp8Move[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDp8Move,1,20000); 

    if(actSuccess!=1)
    {
        printf("in dp8_1_suck, z go back to tube mouth failed\n");
        return 0;
    }

    printf("in dp8_1_suck, z goto pre:%d ok\n",pstSuckParam->posPre);

    //7,suck air2
    if(pstSuckParam->air2Quan > 0)
    {
        stDp8Move[0].sid = sidPump;
        stDp8Move[0].pos = pstSuckParam->air2Quan * coeffUlToSteps_pump; //dj go down to tube mouth
        stDp8Move[0].speed = pstSuckParam->speedSuckAir2 * coeffUlToSteps_pump;
        stDp8Move[0].dec_speed = stDp8Move[0].speed * 4;
        stDp8Move[0].inc_speed = stDp8Move[0].speed * 4;
        stDp8Move[0].dir = 1; //move away origin point      
        actSuccess = uimMoveAct_multi_relative(stDp8Move,1,20000);

        if(actSuccess!=1)
        {
            printf("in dp8_1_suck, suck air2 failed\n");
            return 0;
        }

        if(pstSuckParam->delayAfterSpit > 0)
        {
            usleep(1000*pstSuckParam->delayAfterSpit);
        }
    }

    

    //8, z go up to 0
    stDp8Move[0].sid = sidz;
    stDp8Move[0].pos = 0; //dj z goto 0
    stDp8Move[0].dec_speed = 80000;
    stDp8Move[0].inc_speed = 80000;
    stDp8Move[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDp8Move,1,20000);

    if(actSuccess!=1)
    {
        printf("in dp8_1_suck, z go back to 0 failed\n");
        return 0;
    }

    return actSuccess;
}

int dp8_1convertSpitParam_multi(void * paramIn, void * spitParamOut,void * layoutParamOut)
{
    char * pstMsgData = (char *)paramIn;
    int actSuccess = 0;

    //1, parse the first spit hole. x, y
    location_layout * pstLayoutData = (location_layout *)layoutParamOut;
    location_axis locAxis;


    memcpy(pstLayoutData,pstMsgData,sizeof(location_layout));

    if(pstLayoutData->location_type == DP8_PCR_BUFF_TIP)
    {
        pstLayoutData->location_type == DP8_PCR_BUFF_TIP_1;
    }
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    pstLayoutData->location_type,
    pstLayoutData->indexX,
    pstLayoutData->indexY,
    pstLayoutData->column_x,
    pstLayoutData->row_y);

    //int moduleLiquidType = DJ_PURIFY_LIQUID_TYPE;   

    unsigned char liquidType = VISCOSITY_LOW;
    int spitVolume = 0;
    char * pstDataBuff = pstMsgData + sizeof(location_layout);
    //|xylayout|spitVolume|isformulti|remainVolume
    int remainVolume = 1000;
    //read out the liquid type 
    CResource_Manage  * pstResManage = getResourceManage();

    // if(pstResManage)
    // {
    //    liquidType = pstResManage->get_curr_liquid_type( moduleLiquidType); 
    // }

    //pstDataBuff += sizeof(int);
    memcpy(&spitVolume,pstDataBuff,sizeof(int));

    int isForMulti = 0;
    pstDataBuff += sizeof(int);
    memcpy(&isForMulti,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));


    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,spitVolume,isForMulti);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp1_suck, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }

    int volumeAir2 = dp8_1SuckCtlParam[liquidType].air2;
    int suckBackVolume = 5;

    if(isForMulti)
    {
        volumeAir2 = 0;
        suckBackVolume = 0;
    }



    dynamic_z z_height_pos;
    CGpLayout * pstLayout = CGpLayout::get_instance();
    int zlocValid = pstLayout->getZloc(pstLayoutData->location_type,&z_height_pos);
    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }   
    
    printf("z tube mouth:%d,z max:%d\n",z_height_pos.z_tube_mouth,z_height_pos.z_max);

    int posPre = z_height_pos.z_tube_mouth;

    //suck_param * pstSuckParam = (suck_param *)spitParamOut;
    
    float liquid_height = 0;
    int convertRet = volumeToHeight_en(remainVolume+spitVolume,CONTAINER_PCR_BOARD,&liquid_height); 
    
    int deltaHeightSteps = liquid_height*coeffmmToStep_dp8_1Z;

    int liquidFaceSteps = z_height_pos.z_max - deltaHeightSteps;

    if(liquidFaceSteps<z_height_pos.z_tube_mouth || liquidFaceSteps > z_height_pos.z_max)
    {
        printf("djconvertSpitParam, liquid face height is invalid\n");
        return 0;
    }

    printf("spitparam, z_max:%d,mouth:%d,deltaHeightSteps:%d\n",
    z_height_pos.z_max,z_height_pos.z_tube_mouth,deltaHeightSteps);

    int posPost = z_height_pos.z_tube_mouth - 1000;
    if(posPost < 0)
    {
       posPost = 0; 
    }

    tecan_liquid_param spitParam = {
        .posPre = liquidFaceSteps,
        .posPost = posPost,
        .posMax = z_height_pos.z_max,
        .quantity = spitVolume, // the unit is uL
        .quanSpitAir1 = volumeAir2,//dp1SuckCtlParam[liquidType].air2,
        .quanSuckBack = suckBackVolume,
        .speed = 50,//400 ul/s * 4000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(400*coeffmmToStep_dp8_1Z), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
    };

    memcpy(spitParamOut,&spitParam,sizeof(tecan_liquid_param));

    return 1;
}

int dp8_1_spit_once(void * paramIn,int zGoOrigin)
{
    int actSuccess = 0;
    int sidx = SID_DP8_X;
    int sidy = SID_DP8_Y;
    int sidz = SID_DP8_1_Z;
    int sidPump = SID_DP8_1_PUMP;

    int z_tube_mouth = 0;
    float coeffUlToSteps_pump = 320;//32000steps<-->2500ul for pump
    tecan_liquid_param * spitParam = (tecan_liquid_param * )paramIn;
    
    //1, z go to the pos after spit. 
    move_param stDjMove[2];
    stDjMove[0].sid = sidz;
    stDjMove[0].pos = spitParam->posPre; //dj go down to height of after spitting
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    stDjMove[0].speed = 20000;

    actSuccess = uimMoveAct_multi(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dp8_1_spit_once, z go to pre pos failed\n");
        return 0;
    }
    
    //2, spit out the air
    if(spitParam->quanSpitAir1 > 0)
    {
        stDjMove[0].sid = sidPump;
        stDjMove[0].pos = spitParam->quanSpitAir1 * coeffUlToSteps_pump; //dj go down to height of after spitting
        stDjMove[0].speed = spitParam->speed*coeffUlToSteps_pump;
        stDjMove[0].dec_speed = 4*stDjMove[0].speed;
        stDjMove[0].inc_speed = stDjMove[0].dec_speed;
        
        stDjMove[0].dir = 0; //go toward origin

        actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);
        if(actSuccess!=1)
        {
            printf("in dp8_1_spit_once, spit out air1 failed\n");
            return 0;
        }
    }    
    //3, spit out the liquid
    stDjMove[0].sid = sidPump;
    stDjMove[0].pos = spitParam->quantity * coeffUlToSteps_pump; //dj go down to height of after spitting
    stDjMove[0].speed = spitParam->speed*coeffUlToSteps_pump;
    stDjMove[0].dec_speed = 4*stDjMove[0].speed;
    stDjMove[0].inc_speed = stDjMove[0].dec_speed;
    
    stDjMove[0].dir = 0; //go toward origin

    printf("spit out %f ul\n",spitParam->quantity);

    actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dj_spit_once, spit out liquid failed\n");
        return 0;
    }

    if(spitParam->delayAfterSpit > 0)
    {
        usleep(1000*spitParam->delayAfterSpit);
    }

    //4, z go up to tube mouth.
    stDjMove[0].sid = sidz;
    stDjMove[0].pos = spitParam->posPost; //dj go up to tube mouth
    stDjMove[0].speed = 20000;
    stDjMove[0].dec_speed = 80000;
    stDjMove[0].inc_speed = 80000;
    
    stDjMove[0].dir = 0; //go toward origin

    actSuccess = uimMoveAct_multi(stDjMove,1,20000);
    if(actSuccess!=1)
    {
        printf("in dp8_1_spit_once, z go back up to tube mouth failed\n");
        return 0;
    }

    //5, suck back.
    if(spitParam->quanSuckBack>0.0001)
    {
        stDjMove[0].sid = sidPump;
        stDjMove[0].pos = spitParam->quanSuckBack*coeffUlToSteps_pump; //dj go down to height of after spitting
        stDjMove[0].speed = spitParam->speedSuckBack * coeffUlToSteps_pump;
        stDjMove[0].dec_speed = stDjMove[0].speed * 4;
        stDjMove[0].inc_speed = stDjMove[0].dec_speed;
        
        stDjMove[0].dir = 1; //go away origin

        actSuccess = uimMoveAct_multi_relative(stDjMove,1,20000);
        if(actSuccess!=1)
        {
            printf("in dp8_1_spit_once, suck back failed\n");
            return 0;
        }
    }

    //6, z go up

    if(zGoOrigin)
    {
        stDjMove[0].sid = sidz;
        stDjMove[0].pos = 0; //dj go down to height of after spitting
        stDjMove[0].speed = 20000;
        stDjMove[0].dec_speed = 80000;
        stDjMove[0].inc_speed = 80000;
        
        stDjMove[0].dir = 0; //go toward origin

        actSuccess = uimMoveAct_multi(stDjMove,1,20000);
        if(actSuccess!=1)
        {
            printf("in dp8_1_spit_once, z go back up to tube mouth failed\n");
            return 0;
        } 
    }

    return actSuccess;   

}

int dp8_1_spit_multi(void * pstSpitParamIn,void * firstSpitPos,void * holeArr, int dataLen)
{
    tecan_liquid_param * pstSpitParam = (tecan_liquid_param *)pstSpitParamIn;

    location_layout * pstLayoutData = (location_layout *)firstSpitPos;

    if(dataLen<0)
    {
        printf("dp8_1_spit_multi,param len is invalid\n");
        return 0;
    }
    
    char * holes = (char *)holeArr;
    int holeNum = (dataLen >> 2) + 1; 

    signed char deltaX = 0;
    signed char deltaY = 0;   

    CGpLayout * pstLayout = CGpLayout::get_instance();

    int actSuccess = 0;
    int sidx = SID_DP8_X;
    int sidy = SID_DP8_Y;
    int sidz = SID_DP8_1_Z;
    int sidPump = SID_DP8_1_PUMP;

    int z_tube_mouth = 0;
    float coeffUlToSteps_pump = 320;//32000steps<-->2500ul for pump

    location_layout stLayoutDataReal;

    memcpy(&stLayoutDataReal,pstLayoutData,sizeof(location_layout));
    location_layout stLayoutDataTemp;

    memcpy(&stLayoutDataTemp,&stLayoutDataReal,sizeof(location_layout));

    location_axis axisLoc;
    unsigned short spitVolume = 0;
    int convertRet = 0;
    for(int i=0;i<holeNum;i++)
    {
        if(i>0)
        {
            deltaX = *holes;
            deltaY = *(holes+1);
            memcpy(&spitVolume,holes+2,sizeof(short));

            pstSpitParam->quantity = spitVolume;

            holes += 4;
        }

        stLayoutDataReal.column_x = stLayoutDataTemp.column_x + deltaX;
        stLayoutDataReal.row_y = stLayoutDataTemp.row_y +  deltaY;
        printf("x%d,y%d,v%f,v0:%d\n",stLayoutDataReal.column_x,
        stLayoutDataReal.row_y,pstSpitParam->quantity,spitVolume);
        convertRet = pstLayout->convertToAxisLoc(&stLayoutDataReal,&axisLoc);
        if(convertRet)
        {
            printf("in dp8_1_spit_multi, convert location failed,ix=%d,iy=%d\n",
            stLayoutDataReal.column_x,stLayoutDataReal.row_y);
            actSuccess = 0;
            break;
        }
        else
        {
            printf("in dp8_1_spit_multi, x=%d,y=%d\n",axisLoc.x,axisLoc.y);
        }
        if(i==0)
        {
            actSuccess = dp8XY_move(&axisLoc);
        }
        else
        {
            actSuccess = dp8XY_move_withoutZup(&axisLoc);//djXY_Move(&axisLoc,isPurify);//djXY_Move_withoutZup(&axisLoc,isPurify);
        }

        if(actSuccess!=1)
        {
            printf("in dp8_1_spit_multi,x,y move failed\n");
            actSuccess = 0;
            break;
        }
        
        if(i == (holeNum-1))
        {
            actSuccess = dp8_1_spit_once(pstSpitParam,1);
            //sleep(1);  
        }
        else
        {
            actSuccess = dp8_1_spit_once(pstSpitParam,0);
            //sleep(1);              
        }

        if(!actSuccess)
        {
            printf("in dp8_1_spit_multi, spit once failed\n");
            actSuccess = 0;
            break;
        }
              
    }

    return actSuccess;
}

int dp8_1convertSpitParam(void * paramIn, void * paramOut)
{
    act_msg_node * pstActMsg = (act_msg_node *)paramIn;
    int actSuccess = 0;

    //1, go to target location
    location_layout locLayout;
    location_axis locAxis;
    memcpy(&locLayout,(char*)pstActMsg->paramData,sizeof(location_layout));
    printf("location_type:%d,mx:%d,my:%d,ix:%d,iy:%d\n",
    locLayout.location_type,
    locLayout.indexX,
    locLayout.indexY,
    locLayout.column_x,
    locLayout.row_y);

//    int moduleLiquidType = DJ_PURIFY_LIQUID_TYPE;

//    if(pstActMsg->msgHead.moduleType == MODULE_DJ_PURIFY)
//    {
//        isPurify = 1;
//    }
//    else if(pstActMsg->msgHead.moduleType == MODULE_DJ_QPCR)
//    {
//        isPurify = 0;
//        moduleLiquidType = DJ_QPCR_LIQUID_TYPE;
//    }
//    else
//    {
//        printf("in djconvertSuckParam, module type is invalid\n");
//        return 0;
//    }
    CGpLayout * pstLayout = CGpLayout::get_instance();

    if(locLayout.location_type == DP8_PCR_BUFF_TIP)
    {
        locLayout.location_type = DP8_PCR_BUFF_TIP_1;
    }
    int convertRet = pstLayout->convertToAxisLoc(&locLayout,&locAxis);
    if(convertRet)
    {
        printf("dp8_1convertSpitParam, convert location failed,errorNum:%d\n",convertRet);
    }
    else 
    {
        printf("x=%d,y=%d\n",locAxis.x,locAxis.y);

        actSuccess = dp8XY_move(&locAxis);
    }
    
    if(actSuccess!=1)
    {
        printf("in dp8_1convertSpitParam, x,y go to target location failed\n");
        return 0;
    }
    unsigned char liquidType = VISCOSITY_LOW;
    int spitVolume = 0;
    char * pstDataBuff = ((char*)pstActMsg->paramData) + sizeof(location_layout);
    //|xylayout|spitVolume|isformulti|remainVolume
    int remainVolume = 1000;
    //read out the liquid type 
    CResource_Manage  * pstResManage = getResourceManage();

//    if(pstResManage)
//    {
//       liquidType = pstResManage->get_curr_liquid_type( moduleLiquidType); 
//    }

    //pstDataBuff += sizeof(int);
    memcpy(&spitVolume,pstDataBuff,sizeof(int));

    int isForMulti = 0;
    pstDataBuff += sizeof(int);
    memcpy(&isForMulti,pstDataBuff,sizeof(int));

    pstDataBuff += sizeof(int);
    memcpy(&remainVolume,pstDataBuff,sizeof(int));


    printf("liquidType:%d,volume:%d, isForMulti:%d\n",liquidType,spitVolume,isForMulti);
    if(liquidType >= VISCOSITY_DUMMY || liquidType < VISCOSITY_LOW)
    {
        printf("in dp8_1convertSpitParam, liquidType is %d,change to VISCOSITY_LOW\n");
        liquidType = VISCOSITY_LOW;
    }

    int volumeAir2 = dp8_1SuckCtlParam[liquidType].air2;
    int suckBackVolume = 5;

    if(isForMulti)
    {
        volumeAir2 = 0;
        suckBackVolume = 0;
    }

    dynamic_z z_height_pos;
    int zlocValid = pstLayout->getZloc(locLayout.location_type,&z_height_pos);
    if(!zlocValid)
    {
        printf("z location is not valid\n");
        return 0;
    }   
    
    printf("z tube mouth:%d,z max:%d\n",z_height_pos.z_tube_mouth,z_height_pos.z_max);

    int posPre = z_height_pos.z_tube_mouth;

    suck_param * pstSuckParam = (suck_param *)paramOut;
    
    float liquid_height = 0;
    convertRet = volumeToHeight_en(remainVolume+spitVolume,CONTAINER_PCR_BOARD,&liquid_height); 
    
    int deltaHeightSteps = liquid_height*coeffmmToStep_dp8_1Z;

    int liquidFaceSteps = z_height_pos.z_max - deltaHeightSteps;

    if(liquidFaceSteps<z_height_pos.z_tube_mouth || liquidFaceSteps > z_height_pos.z_max)
    {
        printf("dp8_1convertSpitParam, liquid face height is invalid\n");
        return 0;
    }

    tecan_liquid_param spitParam = {
        .posPre = liquidFaceSteps,
        .posPost = z_height_pos.z_tube_mouth,
        .posMax = z_height_pos.z_max,
        .quantity = spitVolume, // the unit is uL
        .quanSpitAir1 = volumeAir2,//dp1SuckCtlParam[liquidType].air2,
        .quanSuckBack = suckBackVolume,
        .speed = 50,//400 ul/s * 4000inc/1000ul
        .delayAfterSpit = 300, // ms
        .speedGoUp = (int)(400*coeffmmToStep_dp8_1Z), // speed when go up back
        .speedSuckBack = 50,//speed suck back ul/s
    };

    memcpy(paramOut,&spitParam,sizeof(tecan_liquid_param));

    return 1;

}

int dp8_pump_ctl(int isSuck, int volume)
{
    int sidPump = SID_DP8_SUCK;

    float coeffUlToSteps = coeffUlToSteps_suck;//32000steps<-->2500ul for pump
    
    move_param moveParam;
    memset(&moveParam,0,sizeof(move_param));

    moveParam.dec_speed = 8000;
    moveParam.inc_speed = 8000;
    moveParam.speed = 8000;
    moveParam.sid = sidPump;
    if(isSuck)
    {
        moveParam.dir = 1;
    }
    else
    {
        moveParam.dir = 0;
    } 
    moveParam.pos =   coeffUlToSteps * volume;

    return uimMoveAct_multi_relative(&moveParam,1,20000);
}

int dp8_1_pump_ctl(int isSuck, int volume)
{
    int sidPump = SID_DP8_1_PUMP;

    float coeffUlToSteps = 320;//32000steps<-->100ul for pump
    
    move_param moveParam;
    memset(&moveParam,0,sizeof(move_param));

    moveParam.dec_speed = 8000;
    moveParam.inc_speed = 8000;
    moveParam.speed = 8000;
    moveParam.sid = sidPump;
    if(isSuck)
    {
        moveParam.dir = 1;
    }
    else
    {
        moveParam.dir = 0;
    } 
    moveParam.pos =   coeffUlToSteps * volume;

    return uimMoveAct_multi_relative(&moveParam,1,20000);
}


int dp8_single_move_pos(void * paramIn)
{
    int actSuccess = 0;
    int component = -1;
    char * pData = (char *)paramIn;

    location_layout locLayout;

    memcpy(&component,pData,sizeof(int));
    pData += sizeof(int);
    memcpy(&locLayout,pData,sizeof(location_layout));

    if(component == MT_DP8_ABANDONED_HATCH)
    {
        door_move stDoorMove;
        pthread_t doorMoveHandle;
        int indexPos = locLayout.location_type;

        int doorIndexArr[4] = {EN_WASTE_DOOR_CLOSE,
        EN_WASTE_DOOR_DROPTIP1,
        EN_WASTE_DOOR_DROPTIP8,
        EN_WASTE_DOOR_WASTE_LIQUID};

        stDoorMove.result = 0;
        stDoorMove.doorPos = doorIndexArr[indexPos];
            
        pthread_create(&doorMoveHandle,NULL,thread_open_waste_door,&stDoorMove);
        

        pthread_join(doorMoveHandle,NULL);

        actSuccess = stDoorMove.result;
    }

    return actSuccess;
}

